﻿using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace Sgr.EntityFrameworkCore.EntityConfigurations
{
    /// <summary>
    /// Decimal 精度语义化扩展。
    /// 目标：为常见业务语义（金额、数量、单价、费率）提供统一精度设置，提升可读性与多数据库（SQL Server / PostgreSQL 等）兼容性。
    ///
    /// 精度约定（可根据业务再扩展）：
    /// - 金额 Money / Amount       : (18,4)  最终结算/对账金额、行金额、合计金额
    /// - 数量 Quantity             : (15,6)  库存 / 入出库 / 生产领料 / 单位换算基数
    /// - 单价 UnitPrice / Cost     : (15,6)  采购价 / 销售价 / 成本单价 / 移动平均价
    /// - 费率 Rate / 百分比 / 汇率 : (18,6)  税率 / 汇率 / 折扣率 / 分摊比例
    ///
    /// 使用示例（在实体配置中）：
    /// builder.Property(x => x.TotalAmount).HasMoney().HasDefaultValue(0m);
    /// builder.Property(x => x.Qty).HasQuantity();
    /// builder.Property(x => x.UnitPrice).HasUnitPrice();
    /// builder.Property(x => x.ExchangeRate).HasRate();
    ///
    /// 可空字段同样适用（decimal?）：
    /// builder.Property(x => x.DiscountRate).HasRate();
    ///
    /// 推荐做法：
    /// 1. 中间计算过程保持高精度（单价/数量/汇率），最终金额写库前统一 Round(2)。
    /// 2. 避免在不同实体中随意写散乱的 HasPrecision，提高一致性与后期调优可控性。
    /// 3. 若未来精度策略需调整（例如数量改 6 位），集中改此处即可。
    /// </summary>
    public static class DecimalPrecisionExtensions
    {
        // 精度常量（如需全局统一管理，可迁移到 ErpConstant）
        public const int MONEY_P = 18;

        public const int MONEY_S = 4;

        public const int QTY_P = 15;
        public const int QTY_S = 6;

        public const int PRICE_P = 15;
        public const int PRICE_S = 6;

        public const int RATE_P = 18;
        public const int RATE_S = 6;

        /// <summary>
        /// 金额（最终对账/展示）
        /// </summary>
        public static PropertyBuilder<decimal> HasMoney(this PropertyBuilder<decimal> builder) =>
            builder.HasPrecision(MONEY_P, MONEY_S);

        /// <summary>
        /// 金额（最终对账/展示）
        /// </summary>
        public static PropertyBuilder<decimal?> HasMoney(this PropertyBuilder<decimal?> builder) =>
            builder.HasPrecision(MONEY_P, MONEY_S);

        /// <summary>
        /// 数量（库存/换算基数）
        /// </summary>
        public static PropertyBuilder<decimal> HasQuantity(this PropertyBuilder<decimal> builder) =>
            builder.HasPrecision(QTY_P, QTY_S);

        /// <summary>
        /// 数量（库存/换算基数）
        /// </summary>
        public static PropertyBuilder<decimal?> HasQuantity(this PropertyBuilder<decimal?> builder) =>
            builder.HasPrecision(QTY_P, QTY_S);

        /// <summary>
        /// 单价 / 成本单价
        /// </summary>
        public static PropertyBuilder<decimal> HasUnitPrice(this PropertyBuilder<decimal> builder) =>
            builder.HasPrecision(PRICE_P, PRICE_S);

        /// <summary>
        /// 单价 / 成本单价
        /// </summary>
        public static PropertyBuilder<decimal?> HasUnitPrice(this PropertyBuilder<decimal?> builder) =>
            builder.HasPrecision(PRICE_P, PRICE_S);

        /// <summary>
        /// 费率 / 比例 / 汇率
        /// </summary>
        public static PropertyBuilder<decimal> HasRate(this PropertyBuilder<decimal> builder) =>
            builder.HasPrecision(RATE_P, RATE_S);

        /// <summary>
        /// 费率 / 比例 / 汇率
        /// </summary>
        public static PropertyBuilder<decimal?> HasRate(this PropertyBuilder<decimal?> builder) =>
            builder.HasPrecision(RATE_P, RATE_S);
    }
}